---
title: Speed Optimization
sidebarTitle: Speed Optimization
description: Optimize Stagehand performance for faster automation and reduced latency
---

Stagehand performance depends on several factors: DOM processing speed, LLM inference time, browser operations, and network latency. This guide provides proven strategies to maximize automation speed.

## Quick Performance Wins

### 1. Plan Ahead with Observe


Use a single `observe()` call to plan multiple actions, then execute them efficiently:

<CodeGroup>
```typescript TypeScript
// Instead of sequential operations with multiple LLM calls
await page.act("Fill name field");        // LLM call #1
await page.act("Fill email field");       // LLM call #2
await page.act("Select country dropdown"); // LLM call #3

// Use single observe to plan all form fields - one LLM call
const formFields = await page.observe("Find all form fields to fill");

// Execute all actions without LLM inference
for (const field of formFields) {
  await page.act(field); // No LLM calls!
}

```
```python Python
import asyncio

# Instead of sequential operations with multiple LLM calls
await page.act("Fill name field")        # LLM call #1
await page.act("Fill email field")       # LLM call #2  
await page.act("Select country dropdown") # LLM call #3

# Use single observe to plan all form fields - one LLM call
form_fields = await page.observe("Find all form fields to fill")

# Execute all actions without LLM inference
for field in form_fields:
    await page.act(field) # No LLM calls!

```
</CodeGroup>

<Note>
**Performance Tip**: Acting on `observe` results avoids LLM inference entirely. This approach is 2-3x faster than direct `act()` calls and is the recommended pattern for multi-step workflows.
</Note>

<Card title="Caching Guide" icon="database" href="/best-practices/caching">
  Learn advanced caching patterns and cache invalidation strategies
</Card>

### 2. Optimize DOM Processing

Reduce DOM complexity before Stagehand processes the page:

<CodeGroup>
```typescript TypeScript
// Remove heavy elements that slow down processing
await page.evaluate(() => {
  // Remove video elements
  document.querySelectorAll('video, iframe').forEach(el => el.remove());
  
  // Hide complex animations
  document.querySelectorAll('[style*="animation"]').forEach(el => {
    (el as HTMLElement).style.animation = 'none';
  });
});

// Then perform Stagehand operations
await page.act("Click the submit button");
```
```python Python
# Remove heavy elements that slow down processing
await page.evaluate("""
() => {
  // Remove video elements
  document.querySelectorAll('video, iframe').forEach(el => el.remove());
  
  // Hide complex animations
  document.querySelectorAll('[style*="animation"]').forEach(el => {
    el.style.animation = 'none';
  });
}
""")

# Then perform Stagehand operations
await page.act("Click the submit button")
```
</CodeGroup>

### 3. Set Appropriate Timeouts

Use shorter timeouts for simple operations and longer ones for complex page loads:

<CodeGroup>
```typescript TypeScript
// Simple actions - reduce action timeout
await page.act({ 
  instruction: "Click the login button",
  actTimeout: 5000  // Default is 30000ms, reduce for simple clicks
});

// Complex page loads - optimize navigation
await page.goto("https://heavy-spa.com", {
  waitUntil: "domcontentloaded", // Don't wait for all resources
  timeout: 15000 // Shorter than default 30s
});
```
```python Python
# Simple actions - reduce action timeout
await page.act("Click button", act_timeout=5000)


# Complex page loads - optimize navigation
await page.goto("https://heavy-spa.com", 
    wait_until="domcontentloaded",
    timeout=15000
)
```
</CodeGroup>

## Advanced Performance Strategies


### Smart Model Selection

Use faster models for simple tasks, premium models only when needed:

<CodeGroup>
```typescript TypeScript
class SpeedOptimizedStagehand {
  private fastModel: Stagehand;
  private premiumModel: Stagehand;

  async smartAct(page: Page, prompt: string, complexity: 'simple' | 'complex') {
    const model = complexity === 'simple' ? this.fastModel : this.premiumModel;
    return await model.page.act(prompt);
  }
}

// Use fast model for simple clicks/forms
await stagehand.smartAct(page, "Click submit", 'simple');

// Use premium model for complex reasoning
await stagehand.smartAct(page, "Find the cheapest flight option", 'complex');
```
```python Python
class SpeedOptimizedStagehand:
    def __init__(self):
        self.fast_model = Stagehand(model_name="fast-model")
        self.premium_model = Stagehand(model_name="premium-model")
    
    async def smart_act(self, page, prompt: str, complexity: str):
        model = self.fast_model if complexity == 'simple' else self.premium_model
        return await model.page.act(prompt)

# Use fast model for simple clicks/forms
await stagehand.smart_act(page, "Click submit", 'simple')

# Use premium model for complex reasoning  
await stagehand.smart_act(page, "Find the cheapest flight option", 'complex')
```
</CodeGroup>

<Card title="Model Configuration" icon="brain" href="/configuration/models">
  Compare model performance and costs
</Card>

### Page Load Optimization

Skip unnecessary resources during page loads:

<CodeGroup>
```typescript TypeScript
// Block heavy resources globally
await context.route('**/*', (route) => {
  const resourceType = route.request().resourceType();
  if (['image', 'font', 'media'].includes(resourceType)) {
    route.abort();
  } else {
    route.continue();
  }
});

// Use faster navigation
await page.goto(url, { 
  waitUntil: 'domcontentloaded',  // Don't wait for images/fonts
  timeout: 10000 
});
```
```python Python
# Block heavy resources globally
async def handle_route(route):
    resource_type = route.request.resource_type
    if resource_type in ['image', 'font', 'media']:
        await route.abort()
    else:
        await route.continue_()

await context.route('**/*', handle_route)

# Use faster navigation
await page.goto(url, 
    wait_until='domcontentloaded',  # Don't wait for images/fonts
    timeout=10000
)
```
</CodeGroup>
<Card title="Cost Optimization" icon="dollar-sign" href="/best-practices/cost-optimization">
  Balance speed with cost considerations
</Card>

## Performance Monitoring and Benchmarking

Track performance metrics and measure optimization impact:

### Performance Tracking

<CodeGroup>
```typescript TypeScript
class PerformanceTracker {
  private speedMetrics: Map<string, number[]> = new Map();

  async timedAct(page: Page, prompt: string): Promise<ActResult> {
    const start = Date.now();
    const result = await page.act(prompt);
    const duration = Date.now() - start;
    
    if (!this.speedMetrics.has(prompt)) {
      this.speedMetrics.set(prompt, []);
    }
    this.speedMetrics.get(prompt)!.push(duration);
    
    console.log(`Action "${prompt}" took ${duration}ms`);
    return result;
  }

  getAverageTime(prompt: string): number {
    const times = this.speedMetrics.get(prompt) || [];
    return times.reduce((a, b) => a + b, 0) / times.length;
  }
}
```
```python Python
import time
from collections import defaultdict

class PerformanceTracker:
    def __init__(self):
        self.speed_metrics = defaultdict(list)
    
    async def timed_act(self, page, prompt: str):
        start = time.time()
        result = await page.act(prompt)
        duration = (time.time() - start) * 1000  # Convert to ms
        
        self.speed_metrics[prompt].append(duration)
        print(f'Action "{prompt}" took {duration:.0f}ms')
        return result
    
    def get_average_time(self, prompt: str) -> float:
        times = self.speed_metrics[prompt]
        return sum(times) / len(times) if times else 0
```
</CodeGroup>

Example Output:
```
Action "Fill form" took 1000ms
Action "Click submit" took 2000ms
Action "Confirm submission" took 5000ms
```

### Before vs After Benchmarking

<CodeGroup>
```typescript TypeScript
// Before optimization
console.time("workflow");
await page.act("Fill form");
await page.act("Click submit");
await page.act("Confirm submission");
console.timeEnd("workflow"); // 8000ms

// After optimization with observe planning
console.time("workflow-optimized");
const workflowActions = await page.observe("Find form, submit, and confirm elements");

// Execute actions sequentially to avoid conflicts
for (const action of workflowActions) {
  await page.act(action);
}
console.timeEnd("workflow-optimized"); // 500ms
```
```python Python
import time

# Before optimization  
start = time.time()
await page.act("Fill form")
await page.act("Click submit") 
await page.act("Confirm submission")
print(f"Workflow took {(time.time() - start) * 1000:.0f}ms")  # 8000ms

# After optimization with observe planning
start = time.time()
workflow_actions = await page.observe("Find form, submit, and confirm elements")

# Execute actions sequentially to avoid conflicts
for action in workflow_actions:
    await page.act(action)
print(f"Optimized workflow took {(time.time() - start) * 1000:.0f}ms")  # 500ms
```
</CodeGroup>

Example Output:
```
Workflow took 8000ms
Optimized workflow took 500ms
```

<CardGroup cols={1}>
<Card title="Observability & Metrics" icon="chart-line" href="/configuration/observability">
  Set up comprehensive performance monitoring
</Card>
</CardGroup>


## Related Resources

<CardGroup cols={2}>
<Card title="Caching Strategies" icon="database" href="/best-practices/caching">
  Advanced caching patterns for maximum performance
</Card>

<Card title="Cost Optimization" icon="dollar-sign" href="/best-practices/cost-optimization">
  Balance speed improvements with cost considerations
</Card>

<Card title="Browser Configuration" icon="window-maximize" href="/configuration/browser">
  Optimize Browserbase settings for speed
</Card>

<Card title="Model Selection" icon="brain" href="/configuration/models">
  Choose the right model for speed vs accuracy
</Card>
</CardGroup>